#pragma once

#include "utils.h"
#include <stdint.h>


// FIXME: nem igazan stream-ek... valami mas nevet?


class CCharStream
{
public:
    virtual ~CCharStream() { };

    virtual bool Open() = 0;
    virtual void Close() = 0;    

    virtual int  GetCh() = 0;
    virtual int  PeekCh() = 0;
    virtual void PushBack(int ch) = 0;    

    virtual void Reset() = 0;
    virtual long GetPosition() const = 0;
    virtual void Seek(long pos) = 0;    
};


class CTextFileCharStream: public CCharStream
{
public:
    CTextFileCharStream(const char *filename)       { m_File.Open(filename, "rt"); }
    virtual ~CTextFileCharStream()                  { Close(); }

    virtual bool Open()                             { return (FILE*)m_File != NULL; }
    virtual void Close()                            { m_File.Close(); }

    virtual int  GetCh();
    virtual int  PeekCh()                           { int ch = GetCh(); PushBack(ch); return ch; }
    virtual void PushBack(int ch);

    virtual void Reset()                            { rewind(m_File); }
    virtual long GetPosition() const                { return ftell(m_File); }
    virtual void Seek(long pos)                     { fseek(m_File, pos, SEEK_SET); }

private:
    CStdFile m_File;
};


class CMemCharStream: public CCharStream
{
public:
    CMemCharStream(uint8_t *stream, size_t size);
    CMemCharStream(char *text);
    virtual ~CMemCharStream()                       { Close(); }

    virtual bool Open()                             { return true; }
    virtual void Close();
 
    virtual int  GetCh();
    virtual int  PeekCh()                           { return m_Position < m_Size ? m_pStream[m_Position] : EOF; }
    virtual void PushBack(int ch);

    virtual void Reset()                            { m_Position = 0; }
    virtual long GetPosition() const                { return (long)m_Position; }
    virtual void Seek(long pos);

private:
    uint8_t   *m_pStream;
    size_t  m_Position;
    size_t  m_Size;
};
